/**
 * 文件描述如下：
 * 1. 初始化 场景 相机 渲染器
 * 2. 方便在Webgl.vue中调用
 * 3. 非单例模式 但是也请勿继承
 * 4.
 */

import { PerspectiveCamera, Scene, WebGLRenderer, AmbientLight, Group, Color, GridHelper, Vector2, Vector3, AxesHelper } from 'three'
import * as THREE from 'three'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
import { addGeoJsonPoly } from './addGeoJson.js'
import RaycasterManger from './RaycasterManger.js'
import { canvasMouseDown } from './canvasMouse.js'
import Stats from 'three/addons/libs/stats.module.js'
import { createCustomShape, creatSelectMesh, getGroupLineByName, updateCarPosition, removeCarData, filterColor } from './pro_car.js'
import { mainStore } from '@/store/mainStore.js'
import { disposeObject } from '/src/utils/dispose.js'
import { CLonLatTrans } from '@/views/PerceivedEffect/js/projection.js'

export default class ThreeApp {
  constructor(info) {
    // 初始化属性
    this.container = document.querySelector('#webgl-perceivedEffect')
    this.WIDTH = this.container.clientWidth
    this.HEIGHT = this.container.clientHeight
    this.scene = new Scene()
    this.camera = new PerspectiveCamera(50, this.WIDTH / this.HEIGHT, 0.01, 10000)
    this.renderer = new WebGLRenderer({ antialias: true, alpha: true })
    this.store = mainStore()
    this.triangle = null
    this.carBorderGroup = new Group() //车框线的数据
    this.carBorderGroup.name = 'carBorderGroup'
    this.textMeshGroup = new Group()
    this.textMeshGroup.name = 'textMeshGroup'
    console.log('log', info)
    if (!info) {
      ElMessage.error('请传入经纬度信息')
      info = { lon: 0, lat: 0, angle: 0 }
    }
    this.cLonLatTrans = new CLonLatTrans(info.lon, info.lat, info.angle)

    window.ThreePerceivedEffect = this
  }

  // 初始化所有
  init = () => {
    this.initCamera()
    this.initScene()
    this.initRenderer()
    this.initControls()
    this.initStats()
    this.initGridHelper()
    this.initRaycasterManger()
    this.addGeoJson()
  }

  // 初始化相机
  initCamera = () => {
    this.camera.position.z = 100
    this.camera.up.set(0, 0, 1) // 把 Z 轴设为“上方向”
  }

  // 初始化场景
  initScene = () => {
    // this.axesHelper = new AxesHelper(150)
    // this.scene.add(this.axesHelper)

    const ambientLight = new AmbientLight(0xffffff, 1)
    this.scene.add(ambientLight)
    creatSelectMesh(this.carBorderGroup, 1.5, 3)
    this.scene.add(this.carBorderGroup)
    this.scene.add(this.textMeshGroup)
  }

  // 初始化渲染器
  initRenderer = () => {
    this.renderer.setPixelRatio(window.devicePixelRatio)
    this.renderer.setSize(this.WIDTH, this.HEIGHT)
    this.renderer.setAnimationLoop(this.render)
    this.renderer.setClearColor(0x000000, 1)
    // 绑定鼠标点击事件 对场景中的鼠标事件进行判定
    this.renderer.domElement.addEventListener('mousedown', canvasMouseDown)

    this.container.appendChild(this.renderer.domElement)
    window.addEventListener('resize', () => window.location.reload())
  }

  // 初始化控制器
  initControls = () => {
    this.controls = new OrbitControls(this.camera, this.renderer.domElement)
    // this.controls.enableDamping = true
    // 禁用所有旋转
    // **确保启用平移**
    this.controls.enablePan = true
    this.controls.enableRotate = false
    this.controls.screenSpacePanning = true
  }

  // 初始化射线管理器
  initRaycasterManger = () => {
    this.raycasterManger = new RaycasterManger({
      scene: this.scene,
      camera: this.camera,
    })
  }

  // 初始化 帧率 内存 等信息
  initStats = () => {
    this.stats = new Stats()
    this.container.appendChild(this.stats.dom)
  }

  // 初始化网格
  initGridHelper = () => {
    this.gridHelper = new GridHelper(200, 20, new Color(0x023744), new Color(0x023744))
    this.gridHelper.rotation.x = Math.PI / 2
    this.gridHelper.position.z = -8
    this.scene.add(this.gridHelper)
  }

  // 加载geoJSon
  addGeoJson = async () => {
    addGeoJsonPoly(this.scene, this.cLonLatTrans)
  }

  // 更新车流信息
  updateCarData = (data) => {
    // 3 表示视频数据 无车流信息
    if (this.store.curWsPathId == 3) data = []

    data?.forEach((item) => {
      const name = `carLine_${item.id}`
      const nameText = `text_${item.id}`
      const color = filterColor(item?.label, this.store)
      const line = getGroupLineByName(this.carBorderGroup, name)
      const text = getGroupLineByName(this.textMeshGroup, nameText)

      if (line) updateCarPosition(item, color, line, text)
      if (!line) createCustomShape(color, item, this.carBorderGroup, this.textMeshGroup)
    })

    // 移除id消失的线框
    const idArr = data?.map((item) => item.id)
    removeCarData(this.carBorderGroup, this.textMeshGroup, idArr)
  }

  // 选中更新
  updataTableSelect = (id) => {
    if (window.oldModel) window.oldModel.visible = true
    if (!id) {
      window.mesh.visible = false
      window.mesh.carId = null
      window.mesh.name = 'selectMesh'
      window.mesh.position.set(0, 0, 0)
    } else {
      const line = this.carBorderGroup.children.find((item) => item.carId === id)
      window.mesh.carId = line.carId
      window.mesh.name = line.name
      window.mesh.visible = true
      window.mesh.position.copy(line.position)
      window.mesh.rotation.copy(line.rotation)
      this.store.currentCarId = line.carId

      line.visible = false
      window.oldModel = line
    }
  }

  // 更新2D的dom标签
  updateTip() {
    // 如果没开启显示2d标签 则直接返回
    if (!this.store.isShow2dLabelEffect || window.mesh.carId == null) return

    // 从当前的目标中获取当前选中的标签信息
    this.store.currentEffCarTip = this.store.carData.find((item) => item.id === window.mesh.carId)
  }

  // 更新角度
  updateAngle(angle) {
    if (angle == 'default') {
      console.log(this.camera.position)
      const v3_1 = new Vector3(0, 0, 100)
      const v3_2 = new Vector3(0, 0, 0)
      this.camera.position.copy(v3_1)
      this.controls.target.copy(v3_2)
      this.controls.update()
    } else {
      const { position, focus } = angle
      console.log(position, focus)

      // 转成笛卡尔
      const [x1, y1] = this.cLonLatTrans.lonlat2xy(position)
      const [x2, y2] = this.cLonLatTrans.lonlat2xy(focus)

      let v3_1 = new Vector3(x1, y1, 20)
      const v3_2 = new Vector3(x2, y2, 0)

      if (x1 == x2 && y1 == y2) {
        v3_1 = new Vector3(x1, y1, 70)
      }

      // 将2点连线得到相机朝向

      this.camera.position.copy(v3_1)
      this.controls.target.copy(v3_2)
      this.controls.update()
    }
  }

  // 动画函数
  render = () => {
    if (this.store.currentRoute !== 'perceivedEffect') return
    // console.log(this.camera.position)
    this.renderer.render(this.scene, this.camera)
    this.stats?.update()
    this.controls?.update()
    // 标签渲染器渲染
    // 更新tip的位置
    this.updateTip()
  }

  // 窗口大小调整
  resize = () => {
    const WIDTH = this.container.clientWidth
    const HEIGHT = this.container.clientHeight

    this.camera.aspect = WIDTH / HEIGHT
    this.camera.updateProjectionMatrix()
    this.renderer.setSize(WIDTH, HEIGHT)
    this.renderer.setPixelRatio(window.devicePixelRatio)
  }

  destroyed() {
    // 销毁函数触发了
    disposeObject(this.scene)
  }
}
